#include <iostream>
#include <string>

#include "user.pb.h"
#include "mprpcapplication.h"
#include "rpcprovider.h"

// 假设UserService是一个本地服务, 提供了两个进程内的本地方法：Login() 和GetFriendLists()
class UserService : public fixbug::UserServiceRpc // 使用在rpc服务发布端 (rpc_service_provider)
{
public:
    bool Login(std::string name, std::string pwd)
    {
        std::cout << "Doing local service: Login " << std::endl;
        std::cout << "name: " << name << " pwd: " << pwd << std::endl;
        return false;
    }

    bool Register(uint32_t id, std::string name, std::string pwd)
    {
        std::cout << "doing local service:Register" << std::endl;
        std::cout << "id:" << id << "name:" << name << "pwd:" << pwd << std::endl;
        return true;
    }

    // 重写基类UserServiceRpc的虚函数  下面这些方法都是框架直接调用的
    /* 1.caller => Login(request) ruturns (response) =》 muduo => callee
       2.callee => Login(request) => 重写的Login() =》 本地化处理 =》 callee
       3.callee => ...... ==> caller*/
    void Login(::google::protobuf::RpcController *controller,
               const ::fixbug::LoginRequest *request,
               ::fixbug::LoginResponse *response,
               ::google::protobuf::Closure *done)
    {
        // 1.获取rpc客户端的请求数据
        std::string name = request->name();
        std::string pwd = request->pwd();
        // 2.做本地业务
        bool login_result = Login(name, pwd);
        // 3.填写响应数据
        fixbug::ResultCode *code = response->mutable_result();
        code->set_errcode(1);
        code->set_errmsg("Login do error!");
        response->set_success(login_result);

        // 4执行channel回调操作:执行响应对象数据的序列化和网络发送
        // Closure 类里面有一个 纯虚函数 virtual void Run() = 0;
        done->Run();
    }

    void Register(::google::protobuf::RpcController *controller,
                          const ::fixbug::RegisterRequest *request,
                          ::fixbug::RegisterResponse *response,
                          ::google::protobuf::Closure *done)
    {
        // 0.框架已经从网络上接收到请求数据并反序列化为::fixbug::RegisterRequest
        // 1.获取rpc客户端的请求数据
        uint32_t id = request->id();
        std::string name = request->name();
        std::string pwd = request->pwd();
        // 2.做本地业务
        bool register_result = Register(id, name, pwd);
        // 3.填写响应数据
        fixbug::ResultCode* code = response->mutable_result();
        code->set_errcode(1);
        code->set_errmsg("Register do success!");
        response->set_success(register_result);
        // 4.执行::google::protobuf::Closure 回调操作
        done->Run(); // 会将填写好的response进行序列化通过网络给rpc_cient端 
    }

private:
};

int main(int argc, char **argv)
{
    // 调用框架的初始化操作 provider -i config.conf
    MprpcApplication::Init(argc, argv);

    // 2.把UserService对象发布到rpc节点上
    RpcProvider provider;
    provider.NotifyService(new UserService());
    // 3.启动一个rpc服务发布节点, run以后， 进程进入阻塞状态，等待远程的rpc调用请求
    provider.run(); // 启动了muduo网络服务

    return 0;
}